package com.football.util;

import com.alibaba.fastjson.JSON;
import redis.clients.jedis.*;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author WUREN
 * @desc Jedis客户端工具类
 * @create 2019-02-25 16:03
 **/
public class JedisUtil {

  /**
   * 清空数据
   */
  public static String flushDB() {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.flushDB();
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 判断某个键是否存在
   *
   * @param key
   * @return
   */
  public static boolean exists(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.exists(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 新增/覆盖数据项
   *
   * @param key
   * @param value
   * @return 执行成功返回OK
   */
  public static String set(String key, String value) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.set(key, value);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 不覆盖增加数据项（key重复则不插入）
   *
   * @param key
   * @param value
   * @return 1：插入数据项 0-key重复不插入
   */
  public static Long setnx(String key, String value) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.setnx(key, value);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 增加数据项并设置有效时间（秒）
   *
   * @param key
   * @param seconds 有效时间，单位：秒
   * @param value
   * @return
   */
  public static String setex(String key, int seconds, String value) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.setex(key, seconds, value);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 增加多个键值对
   *
   * @param var1，格式为 String k1,String v1,String k2,String v2,...
   * @return
   */
  public static String mset(String... var1) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.mset(var1);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取多个key对应value
   *
   * @param var1，格式为 String k1,String v1,String k2,String v2,...
   * @return
   */
  public static List<String> mget(String... var1) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.mget(var1);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取所有匹配的key
   *
   * @param pattern 正则模式
   * @return
   */
  public static Set<String> keys(String pattern) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.keys(pattern);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 删除键为key的数据项
   *
   * @param key
   * @return
   */
  public static Long del(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.del(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 删除多个key对应的数据项
   *
   * @param keyArray
   * @return
   */
  public static Long del(String[] keyArray) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.del(keyArray);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 设置键为key数据项的过期时间为seconds秒
   *
   * @param key
   * @return
   */
  public static Long expire(String key, int seconds) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.expire(key, seconds);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取键为key数据项的剩余生存时间（秒）
   *
   * @param key
   * @return
   */
  public static Long ttl(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.ttl(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 移除键为key数据项的生存时间限制
   *
   * @param key
   * @return
   */
  public static Long persist(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.persist(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 查看键为key对应value的数据类型
   *
   * @param key
   * @return
   */
  public static String type(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.type(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取键为key对应的value
   *
   * @param key
   * @return
   */
  public static String get(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.get(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取key对应value并更新value
   *
   * @param key
   * @param value
   * @return
   */
  public static String getSet(String key, String value) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.getSet(key, value);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取key对应value下标start到end之间的字符，包括end指向的字符
   *
   * @param key
   * @param start
   * @param end
   * @return
   */
  public static String getrange(String key, int start, int end) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.getrange(key, start, end);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 在key对应value后面扩展字符串appendStr
   *
   * @param key
   * @param appendStr
   * @return 扩展后的value长度
   */
  public static Long append(String key, String appendStr) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.append(key, appendStr);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 将key对应的value自增1
   *
   * @param key
   * @return
   */
  public static Long incr(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.incr(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 将key对应的value自增step
   *
   * @param key
   * @param step 自增/减步长，整数
   * @return
   */
  public static Long incrBy(String key, int step) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.incrBy(key, step);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 将key对应的value自减1
   *
   * @param key
   * @return
   */
  public static Long decr(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.decr(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 将key对应的value自减step
   *
   * @param key
   * @param step 自减/增步长，整数
   * @return
   */
  public static Long decrBy(String key, int step) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.decrBy(key, step);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   *
   * 列表（List）操作
   *
   */

  /**
   * 添加一个List
   *
   * @param key
   * @param vals
   * @return
   */
  public static Long lpush(String key, String[] vals) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.lpush(key, vals);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 往key对应List左侧插入一个元素val
   *
   * @param key
   * @param val
   * @return
   */
  public static Long lpush(String key, String val) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.lpush(key, val);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取key对应List区间[start, end]的元素，包括end下标指向的元素
   *
   * @param key
   * @param start 开始下标
   * @param end   结束下标
   * @return
   */
  public static List<String> lrange(String key, int start, int end) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.lrange(key, start, end);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 删除指定元素val个数num
   *
   * @param key
   * @param num
   * @param val
   * @return
   */
  public static Long lrem(String key, int num, String val) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.lrem(key, num, val);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 删除list区间[start, end]之外的元素，end下标的元素被保留
   *
   * @param key
   * @param start
   * @param end
   * @return OK：成功
   */
  public static String ltrim(String key, int start, int end) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.ltrim(key, start, end);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * key对应list左端出栈一个元素
   *
   * @param key
   * @return
   */
  public static String lpop(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.lpop(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * key对应list右端插入一个val
   *
   * @param key
   * @param val
   * @return
   */
  public static Long rpush(String key, String val) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.rpush(key, val);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * key对应list右端出栈一个元素
   *
   * @param key
   * @return
   */
  public static String rpop(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.rpop(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 修改key对应list指定下标index的元素值
   *
   * @param key
   * @param index
   * @param val
   * @return
   */
  public static String lset(String key, int index, String val) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.lset(key, index, val);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取key对应list的长度
   *
   * @param key
   * @return
   */
  public static Long llen(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.llen(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取key对应list下标为index的元素
   *
   * @param key
   * @param index
   * @return
   */
  public static String lindex(String key, int index) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.lindex(key, index);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 将key对应list里面的元素从小到大顺序排列
   *
   * @param key
   * @return
   */
  public static List<String> sort(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.sort(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   *
   * 集合（Set）操作
   *
   */

  /**
   * 添加一个Set
   *
   * @param key
   * @param members
   * @return
   */
  public static Long sadd(String key, String... members) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.sadd(key, members);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取key对应set的所有元素
   *
   * @param key
   * @return
   */
  public static Set<String> smembers(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.smembers(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 删除一个值为val的元素
   *
   * @param key
   * @param val
   * @return
   */
  public static Long srem(String key, String val) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.srem(key, val);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 删除值为v1，v2，...的元素
   *
   * @param key
   * @param vals
   * @return
   */
  public static Long srem(String key, String... vals) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.srem(key, vals);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 随机出栈set里的一个元素
   *
   * @param key
   * @return
   */
  public static String spop(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.spop(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取set中的元素个数
   *
   * @param key
   * @return
   */
  public static Long scard(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.scard(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 将元素val从集合key1剪切到key2
   *
   * @param key1
   * @param key2
   * @param val
   * @return
   */
  public static Long smove(String key1, String key2, String val) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.smove(key1, key2, val);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取集合key1和集合key2的交集
   *
   * @param key1
   * @param key2
   * @return
   */
  public static Set<String> sinter(String key1, String key2) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.sinter(key1, key2);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取集合key1和集合key2的并集
   *
   * @param key1
   * @param key2
   * @return
   */
  public static Set<String> sunion(String key1, String key2) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.sunion(key1, key2);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取集合key1和集合key2的差集
   *
   * @param key1
   * @param key2
   * @return
   */
  public static Set<String> sdiff(String key1, String key2) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.sdiff(key1, key2);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   *
   * 哈希（Hash）操作
   */

  /**
   * 添加一个Hash
   *
   * @param key
   * @param map
   * @return
   */
  public static String hmset(String key, Map map) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.hmset(key, map);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 往Hash插入一个元素(k, v)
   *
   * @param key
   * @param k
   * @param v
   * @return
   */
  public static Long hset(String key, String k, String v) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.hset(key, k, v);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取Hash的所有(k, v)元素
   *
   * @param key
   * @return
   */
  public static Map<String, String> hgetAll(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.hgetAll(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取Hash所有元素的Key
   *
   * @param key
   * @return
   */
  public static Set<String> hkeys(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.hkeys(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取Hash所有元素的Value
   *
   * @param key
   * @return
   */
  public static List<String> hvals(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.hvals(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 把Hash中k对应元素的val+=step，step可为负数
   *
   * @param key
   * @param k
   * @param step
   * @return
   */
  public static Long hincrBy(String key, String k, int step) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.hincrBy(key, k, step);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 从Hash删除一个或多个元素
   *
   * @param key
   * @param keys
   * @return
   */
  public static Long hdel(String key, String[] keys) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.hdel(key, keys);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取Hash中元素个数
   *
   * @param key
   * @return
   */
  public static Long hlen(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.hlen(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 判断Hash是否存在k对应元素
   *
   * @param key
   * @param k
   * @return
   */
  public static boolean hexists(String key, String k) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.hexists(key, k);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取Hash中一个或多个元素value
   *
   * @param key
   * @param k
   * @return
   */
  public static List<String> hmget(String key, String[] k) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.hmget(key, k);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   *
   * 有序集合（Zsort）操作
   */

  /**
   * 添加一个ZSet
   *
   * @param key
   * @param map
   * @return
   */
  public static Long zadd(String key, Map<String, Double> map) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.zadd(key, map);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 往ZSet插入一个元素(score,member)
   *
   * @param key
   * @param score
   * @param member
   * @return
   */
  public static Long zadd(String key, double score, String member) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.zadd(key, score, member);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取ZSet里下标[start, end]区间的元素val
   *
   * @param key
   * @param start
   * @param end
   * @return
   */
  public static Set<String> zrange(String key, int start, int end) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.zrange(key, start, end);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取ZSet里下标[start, end]区间的元素(score, val)
   *
   * @param key
   * @param start
   * @param end
   * @return
   */
  public static Set<Tuple> zrangeWithScores(String key, int start, int end) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.zrangeWithScores(key, start, end);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取ZSet里score[min, max]区间元素的val
   *
   * @param key
   * @param min
   * @param max
   * @return
   */
  public static Set<String> zrangeByScore(String key, double min, double max) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.zrangeByScore(key, min, max);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取ZSet里score[start, end]区间的元素(score, val)
   *
   * @param key
   * @param min
   * @param max
   * @return
   */
  public static Set<Tuple> zrangeByScoreWithScores(String key, double min, double max) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.zrangeByScoreWithScores(key, min, max);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取ZSet里val为value的元素的score
   *
   * @param key
   * @return
   */
  public static Double zscore(String key, String value) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.zscore(key, value);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取ZSet里val为value的元素的score排名
   *
   * @param key
   * @param value
   * @return
   */
  public static Long zrank(String key, String value) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.zrank(key, value);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 删除ZSet里val为value的元素
   *
   * @param key
   * @param value
   * @return
   */
  public static Long zrem(String key, String value) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.zrem(key, value);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取ZSet的元素个数
   *
   * @param key
   * @return
   */
  public static Long zcard(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.zcard(key);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 获取ZSet中score在[min, max]区间的元素个数
   *
   * @param key
   * @param min
   * @param max
   * @return
   */
  public static Long zcount(String key, double min, double max) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.zcount(key, min, max);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 把ZSet中val为value的元素score+=increment
   *
   * @param key
   * @param increment
   * @param value
   * @return
   */
  public static Double zincrby(String key, double increment, String value) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.zincrby(key, increment, value);
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 排序操作
   */

  /**
   * 队列按首字母a-z排列
   *
   * @param key
   * @return
   */
  public static List<String> sortByAlpha(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.sort(key, new SortingParams().alpha());
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 队列按数字升序排列
   *
   * @param key
   * @return
   */
  public static List<String> sortByAsc(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.sort(key, new SortingParams().asc());
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * 队列按数字降序排列
   *
   * @param key
   * @return
   */
  public static List<String> sortByDesc(String key) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.sort(key, new SortingParams().desc());
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * java对象序列化存储到Key
   *
   * @param key
   * @param t
   * @param <T>
   * @return
   */
  public static <T> String setObject(String key, T t) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return jedis.set(key, JSON.toJSONString(t));
    } finally {
      RedisPool.close(jedis);
    }
  }

  /**
   * java对象反序列化
   *
   * @param key
   * @param <T>
   * @return
   */
  public static <T> T getObject(String key, Class<T> clazz) {
    Jedis jedis = RedisPool.getInstance();
    try {
      return JSON.parseObject(jedis.get(key), clazz);
    } finally {
      RedisPool.close(jedis);
    }
  }

}
